import {
  FC,
  ReactElement,
  useMemo,
  useCallback,
  useState,
  useRef,
} from "react";
import styled from "styled-components";
import { Form, Input, Button, Space, FormInstance } from "antd";
import { LoadingOutlined } from "@ant-design/icons";
import { useAuth } from "../api/AuthContext";
import { flexCenter } from "../components/BUI/styled";
import { checkUsernameValid } from "../api/authApi";
import { useHistory } from "react-router-dom";
import RASEncrypt from "../utils/JSEncrypt";

interface IProps {}

let time: number | null | NodeJS.Timeout = null;

const Login: FC<IProps> = (): ReactElement => {
  const { login, register } = useAuth();
  const form = useRef<null | FormInstance<any>>(null);
  const [type, setType] = useState("LOGIN"); //LOGIN OR REGISTER
  const [loading, setLoading] = useState(false);
  const [checking, setChecking] = useState(false);
  const [usernameValid, setUsernameValid] = useState(true);
  const {
    replace,
    location: { state },
  } = useHistory();

  const validUsernameCheck = useCallback(async username => {
    setChecking(true);
    const valid = await checkUsernameValid(username);
    setUsernameValid(valid);
    setChecking(false);
  }, []);

  const handleUsernameChange = useCallback(
    ({ target: { value } }) => {
      form.current && form.current.setFields([{ name: "username", value }]);
      time && clearTimeout(time as number);
      time = setTimeout(() => {
        validUsernameCheck(value);
      }, 500);
    },
    [validUsernameCheck, form]
  );

  const ButtonGroup: any = useMemo(
    () => [
      {
        type: "primary",
        htmlType: "submit",
        children: type,
        loading,
      },
      { type: "link", htmlType: "reset", children: "RESET" },
    ],
    [type, loading]
  );

  const toggleType = useCallback(() => {
    setType(type => (type === "LOGIN" ? "REGISTER" : "LOGIN"));
    setChecking(false);
    setUsernameValid(true);
    setLoading(false);
    form.current && form.current.resetFields([]);
  }, []);

  const routeReplace = useCallback(() => {
    // @ts-ignore
    const path = state?.from?.pathname ?? "/admin";
    replace(path);
  }, [replace, state]);

  const handleLogin = useCallback(
    async values => {
      setLoading(true);
      const result = await login(values);
      setLoading(false);
      result && routeReplace();
    },
    [login, routeReplace]
  );

  const handleRegister = useCallback(
    async values => {
      if (!usernameValid) return;
      setLoading(true);
      const auth = await register(values);
      setLoading(false);
      auth && routeReplace();
    },
    [register, routeReplace, usernameValid]
  );

  const onFinish = useCallback(
    values => {
      const JSE = { ...values, password: RASEncrypt(values.password) };
      console.log(values, JSE);
      type === "LOGIN" ? handleLogin(JSE) : handleRegister(JSE);
    },
    [handleLogin, handleRegister, type]
  );

  const suffix = useMemo(
    () => (checking ? <LoadingOutlined /> : <span />),
    [checking]
  );

  return (
    <Container>
      <div>
        <FormWrap>
          <span>Hello</span>
          <Form
            ref={form}
            labelCol={{ span: 8 }}
            wrapperCol={{ span: 15 }}
            onFinish={onFinish}
          >
            <Form.Item
              label='Username'
              name='username'
              rules={[{ required: true, message: "Please input username!" }]}
            >
              {type === "LOGIN" ? (
                <Input />
              ) : (
                <>
                  <Input suffix={suffix} onChange={handleUsernameChange} />
                  <span style={{ color: "#f00" }}>
                    {usernameValid ? null : "用户名已存在"}
                  </span>
                </>
              )}
            </Form.Item>
            <Form.Item
              label='Password'
              name='password'
              rules={[{ required: true, message: "Please input password!" }]}
            >
              <Input.Password maxLength={20} />
            </Form.Item>
            <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
              <Space size='large'>
                {ButtonGroup.map((button: any) => (
                  <Button key={button.children} {...button} />
                ))}
              </Space>
            </Form.Item>
          </Form>
          <RegisterBtn onClick={toggleType} type='link'>
            {type === "LOGIN" ? "REGISTER" : "LOGIN"}
          </RegisterBtn>
        </FormWrap>
      </div>
    </Container>
  );
};

export default Login;

const RegisterBtn = styled(Button)`
  position: absolute;
  bottom: 5px;
  right: 5px;
`;

const FormWrap = styled.div`
  background-color: #ffffff;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  width: 20rem;
  height: 22rem;
  border-radius: 5px;
  ${flexCenter};
  position: relative;
  box-shadow: 0 0 10px 0 #666;
  position: relative;
  padding-top: 7rem;
  & > span {
    position: absolute;
    height: 7rem;
    width: calc(100% - 2rem);
    top: 1rem;
    left: 1rem;
    background: #51f;
    border-radius: 3px;
    color: #fff;
    font-size: 2rem;
    font-weight: bold;
    line-height: 7rem;
    text-align: center;
    letter-spacing: 2px;
  }
`;

const Container = styled.div`
  background-color: #000;
  height: 100vh;
  overflow: hidden;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;

  & > div {
    width: 100%;
    height: 100%;
    /* background: linear-gradient(#feffff, #b7acf7a6, #090909a6); */
    background: linear-gradient(60deg, #faa, #00f);
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 5px 1px #51f;

    input {
      background-color: #bbbaba73 !important;
      border: none;
      border-bottom: 2px solid #000;
    }
  }

  &::before {
    content: "hongbin.xyz";
    color: #fff;
    font-size: 5rem;
    font-weight: bold;
    position: absolute;
    bottom: 0;
    text-shadow: 2px 2px #51f;
    z-index: 1;
    user-select: none;
  }
`;
